home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Graphics Unleashed
/
PC Graphics Unleashed.iso
/
ch05
/
dither.old
< prev
next >
Wrap
Text File
|
1994-07-31
|
10KB
|
253 lines
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<fcntl.h>
#include<io.h>
#include<vsa.h>
#include<vsa_font.h>
#include<tiff.h>
void draw_dithered_pixel(int,int,unsigned char *,int);
int crack_rgb(unsigned char *,int *,int *,int *,float *,
float *,float *);
unsigned long read_tga_header(int,int *,int *,int *,int *);
void true_color_lut(void);
unsigned char dither[4][64]={
{
1 },
{
1, 3,
4, 2 },
{
1, 9, 3, 11,
13, 5, 15, 7,
4, 12, 2, 10,
16, 8, 14, 6 },
{
1, 33, 9, 41, 3, 35, 11, 43,
49, 17, 57, 25, 51, 19, 59, 27,
13, 45, 5, 37, 15, 47, 7, 39,
61, 29, 53, 21, 63, 31, 55, 23,
4, 36, 12, 44, 2, 34, 10, 42,
52, 20, 60, 28, 50, 18, 58, 26,
16, 48, 8, 40, 14, 46, 6, 38,
64, 32, 56, 24, 62, 30, 54, 22 },
};
/*......................... DITHER.C............. 5-29-94 .....*/
/* This program reads True Color (24 bit per pixel) TARGA */
/* images and converts them to 8 bit dithered screen images. */
/* It also writes out the dithered image as an 8 bit per pixel */
/* Palette Color TIFF image. */
/*.............................................................*/
void main()
{
char filename[80];
int i,j,size,width,height,type,file_handle,orient;
unsigned char rgb[3072];
printf("Input TARGA Image Filename: ");
scanf("%s",filename);
LOOP:
/*.............................................................*/
/* Get dither size and limit it to legal value of 1,2,4 or 8. */
/*.............................................................*/
printf("Input Dither Size (1, 2, 4, or 8): ");
scanf("%d",&size);
if(size == 3) size = 4; /* size limited to 1, 2, 4, or 8 */
if(size > 4) size = 8; /* size limited to 1, 2, 4, or 8 */
/*.............................................................*/
/* Set highest video resolution available. */
/*.............................................................*/
if(vsa_init(0x2105) != 0) /* 1024 x 768 x 256 */
if(vsa_init(0x2103) != 0) /* 800 x 600 x 256 */
if(vsa_init(0x2101) != 0) /* 640 x 480 x 256 */
if(vsa_init(0x2100) != 0) /* 640 x 400 x 256 */
{
printf("Can't set VESA video mode\n");
printf("Is VESA BIOS Extension TSR loaded?\n");
return;
}
/*.............................................................*/
/* Open the TARGA file and get header info. */
/*.............................................................*/
if((file_handle = open(filename,O_BINARY | O_RDONLY)) == -1)
return;
read_tga_header(file_handle,&width,&height,&type,&orient);
/*.............................................................*/
/* Set up the Palette as an 8 bit RGB (3,3,2) table. */
/*.............................................................*/
true_color_lut();
/*.............................................................*/
/* Read out pixels from TARGA file and plot on screen in */
/* top down or bottom up order depending on orientation. */
/*.............................................................*/
if(orient == 32)
for(j=0;j<height;j++)
{
read(file_handle,rgb,3*width);
for(i=0;i<width;i++)
draw_dithered_pixel(i,j,rgb+3*i,size);
}
else
for(j=height-1;j>=0;j--)
{
read(file_handle,rgb,3*width);
for(i=0;i<width;i++)
draw_dithered_pixel(i,j,rgb+3*i,size);
}
/*.............................................................*/
/* Close the image file and look for an ESC key to quit. */
/* Otherwise, save dithered image as an 8 bit TIFF called */
/* NEW.TIF and LOOP for experimentation with a different */
/* dither box size. */
/*.............................................................*/
close(file_handle);
if(getch() == 27)
goto SKIP;
tf_save_file(0,0,width-1,height-1,"new.tif");
vsa_set_svga_mode(0x3);
goto LOOP; /*..... Oh No, a goto! .....*/
SKIP:
vsa_set_svga_mode(0x3);
return; /*..... End main .....*/
}
/*.................... DRAW_DITHERED_PIXEL ....... 5-27-94 ....*/
/* This routine draws a dithered pixel at screen coordinate */
/* 'i,j' with 24 bit color equivalent passed in the 3 byte */
/* array 'rgb'. The dither pattern size is specified by 'size'*/
/* and can be 1, 2, 4, or 8. Note that the global 'dither' */
/* array must must be initialized before calling this routine. */
/*.............................................................*/
void draw_dithered_pixel(int i,int j,unsigned char *rgb,int size)
{
int n,m,q,r,red_lvl,grn_lvl,blu_lvl;
int color,red_boost,grn_boost,blu_boost;
float x,y,frl,fgl,fbl;
/*.............................................................*/
/* For the pixels screen address i,j, compute pixel address r */
/* within the dither box. Also select dither box q based on */
/* size (size = 1, 2, 4, or 8). */
/*.............................................................*/
x = (float)i/size;
y = (float)j/size;
m = (int)(size*(x - (int)x) + 0.5);
n = (int)(size*(y - (int)y) + 0.5);
q = size/2;
if(size == 8) q = 3;
r = m+n*size;
/*.............................................................*/
/* Get the Dark Pixel color, the Light Pixel components, and */
/* the pixel color errors. */
/*.............................................................*/
color = crack_rgb(rgb,&red_boost,&grn_boost,&blu_boost,
&frl,&fgl,&fbl);
/*.............................................................*/
/*Scale the pixel color error values based on dither box size */
/*.............................................................*/
red_lvl = size*size*frl;
grn_lvl = size*size*fgl;
blu_lvl = size*size*fbl;
/*.............................................................*/
/*Test the pixels red, green, and blue error values against the*/
/*thresholds in the dither box. Decide which color to use. */
/*.............................................................*/
if(dither[q][r] <= red_lvl)
color = (color & 0x1f) + (red_boost << 5); /* Boost Red */
if(dither[q][r] <= grn_lvl)
color = (color & 0xe3) + (grn_boost << 2); /* Boost Grn */
if(dither[q][r] <= blu_lvl)
color = (color & 0xfc) + blu_boost; /* Boost Blu */
/*.............................................................*/
/* Set color and draw pixel on screen. */
/*.............................................................*/
vsa_set_color(color);
vsa_set_pixel(i,j);
return;
} /*.... END draw_dithered_pixel ....*/
/*.......................... CRACK_RGB ........... 5-27-94 ....*/
/* This routine takes the 24 bit RGB color value in the 'rgb' */
/* array, quantizes it down to an 8 bit color value (3 bit red,*/
/* 3 bit green, and 2 bit blue) and returns this 8 bit */
/* 'base_color' value. It also computes the 8 bit color boost */
/* values '*red_boost', 'grn_boost', and 'blu_boost' which are */
/* used to draw dithered pixels. It also computes the color */
/* error values 'red_lvl', 'grn_lvl', and 'blu_lvl' which */
/* determine when the dither function draws with 'base_color' */
/* and when it draws with 'xxx_boost' color. */
/*.............................................................*/
int crack_rgb(unsigned char *rgb,int *red_boost,int *grn_boost,
int *blu_boost,float *red_lvl,float *grn_lvl,
float *blu_lvl)
{
int base_color,red,grn,blu;
float fred,fgrn,fblu;
fred = rgb[2]/36.6; /*36.6 = (256 shades of red)/(2^3 - 1) */
fgrn = rgb[1]/36.6; /*36.6 = (256 shades of grn)/(2^3 - 1) */
fblu = rgb[0]/85.4; /*85.4 = (256 shades of blu)/(2^2 - 1) */
red = fred;
grn = fgrn;
blu = fblu;
base_color = (red << 5)+(grn << 2)+blu; /*Dark Pixel color */
*red_lvl = fred - red;
*grn_lvl = fgrn - grn;
*blu_lvl = fblu - blu;
*red_boost = red+1; /*This is the Light Pixel color for red */
*grn_boost = grn+1; /*This is the Light Pixel color for grn */
*blu_boost = blu+1; /*This is the Light Pixel color for blu */
return base_color;
} /*.... END crack_rgb .....*/
/*....................... READ_TGA_HEADER ....... 5-17-94 ....*/
/* This routine parses through a TGA header and returns the */
/* file offset in bytes to the first byte of pixel data. */
/* It also returns image width, height, and type (type 2 is the*/
/* uncompressed 24 bit image type). */
/*.............................................................*/
unsigned long read_tga_header(int handle, int *width,
int *height, int *type,
int *orientation)
{
unsigned long offset;
unsigned char buff[18];
read(handle,buff,18);
offset = 18+buff[0];
*type = buff[2];
*width = *((unsigned *)buff + 6);
*height = *((unsigned *)buff + 7);
*orientation = buff[17];
return offset;
} /*.... END read_tga_header .....*/
/*.................... TRUE_COLOR_LUT.C .......... 5-15-94 ....*/
/* This routine generates a 'true color' LUT. An 8 bit index */
/* into the LUT represents 3 bits of RED, 3 bits of GREEN, and */
/* 2 bits of BLUE. The 3 msbs of the 8 bit index are the RED */
/* field, next 3 are GREEN, and the 2 lsbs are the BLUE field. */
/* */
/*.............................................................*/
void true_color_lut(void)
{
int i;
unsigned char color_array[768];
for(i=0;i<256;i++)
{
color_array[3*i+0]= ((i & 0x00e0) >> 5) * 9;
color_array[3*i+1]= ((i & 0x001c) >> 2) * 9;
color_array[3*i+2]= (i & 0x0003) * 21;
}
vsa_write_color_block(0,256,color_array);
return;
} /*..... End true_color_lut .....*/